home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
TPUG - Toronto PET Users Group
/
TPUG Users Group CD
/
TPUG Users Group CD.iso
/
AMIGA
/
AMICUS
/
AMICUS02.ADF
/
Asm
/
bsearch.asm
< prev
next >
Wrap
Assembly Source File
|
1989-05-30
|
6KB
|
172 lines
;[70167,2216]
;BSEARC.ASM 15-Dec-85 5910 1
;
; Keywords: BINARY SEARCH ASSEMBLER UTILITY
;
; The assembler source code to implement the Unix System V bsearch() function
; that does a binary search on a table and returns the location of the sought
; after data. A companion to the qsort() function that sorts the data in a
; table. Bsearch.asm contains its own documentation as comments at the top
; of the file.
;
;
;
RORG 0
XDEF _bsearch
*------------------------------------------------------------------------
* A 68000 assembler implementation of the UNIX System V bsearch() function.
* bsearch - binary search algorithm.
* bsearch is a binary search routine generalized from Knuth (6.2.1)
* algorithm B. It returns a pointer into a table indicating where a
* datum may be found. The table must be previously sorted in increasing
* order according to the provided comparison function. (See qsort.asm for
* how to do this.)
* bsearch should be declared in your C program as follows:
* extern char *bsearch();
* and called as: (assuming location is a variable of type pointer to element)
* location=(ELEMENT *)bsearch((char *) key, (char *) base, nel,
* sizeof(*key),compar);
* where:
* unsigned nel;
* int (*compar) ();
* and
* key points to the datum to be sought in the table.
* base points to the element at the base of the table, (i.e. &table[0])
* nel is the number of elements in the table.
* compar is the name of the comparison function (see qsort.asm), which is
* called with two arguments that point to the elements being compared.
* The function must return an integer less than, equal to, or greater than
* zero according as the first argument is to be considered less than, equal
* to, or greater than the second. NOTE: in Lattice C the function compar
* must be declared extern before it is defined to insure proper argument
* passing orders.
* Diagnostics:
* A NULL pointer is returned if the key cannot be found in the table.
* Notes:
* the comparison function does not need to compare every byte, so arbitrary
* data may be contained in the elements in addition to the values being
* compared.
*------------------------------------------------------------------------
_bsearch:
link a6,#0 * link to caller and
movem.l d4-d7/a2-a5,-(sp) * save registers for restoration.
movea.l 8(a6),a5 * data to be sought in table.
movea.l 12(a6),a4 * base of the table.
move.l 20(a6),d7 * size of table elements.
movea.l 24(a6),a3 * get address of user's compar func.
move.l d7,d0
add.l d7,d0
move.l d0,d6
move.l 16(a6),d0 * number of elements in table.
subq.l #1,d0 * elements run from 0 to n-1.
move.l d0,-(sp) * compute the size of the table in
move.l d7,-(sp) * bytes= number_elements * table_size
jsr unsgmul
addq.l #8,sp
add.l a4,d0 * add base address to size
movea.l d0,a2 * a2 now points to the end of table
BL1:
cmpa.l a4,a2 * make sure table is non-empty.
bcs.l BL2 * i.e. start address <> end address
move.l d6,-(sp) * calculate the mid point element's
move.l a2,d0 * address and leave it on the stack
sub.l a4,d0
move.l d0,-(sp)
jsr unsgdiv
addq.l #8,sp
move.l d0,-(sp)
move.l d7,-(sp)
jsr unsgmul
addq.l #8,sp
add.l a4,d0
move.l d0,d5
move.l d5,-(sp)
move.l a5,-(sp) * along with the sought data's addr.
jsr (a3) * call the user's compar function.
addq.l #8,sp
move.l d0,d4
tst.l d4 * are they equal? (is d4=d0=0?)
bne.s BL4 * recomputed midpoint and retry.
move.l d5,d0 * done
bra.s BL8
BL4:
tst.l d4 * recompute the midpoint by
bge.s BL5 * either moving the ending address
move.l d5,d0 * of the table, (in a2)
sub.l d7,d0
movea.l d0,a2
bra.s BL1
BL5:
move.l d5,d0 * or the starting address ,(in a4)
add.l d7,d0
movea.l d0,a4
BL6:
bra.s BL1 * and try the comparison again.
BL2:
moveq.l #0,d0 * return 0 (NULL pointer) to signify
* * data not found in table.
BL8:
movem.l (sp)+,a5-a2/d7-d4
unlk a6
rts
*
* support routines to do unsigned multiplication and division
*
unsgmul:
lea 4(sp),a0
move.w (a0)+,d0
move.l 8(sp),d1
mulu d1,d0
swap d1
mulu (a0),d1
add.w d1,d0
swap d0
clr.w d0
move.w (a0),d1
mulu 10(sp),d1
add.l d1,d0
move.l d0,-2(a0)
rts
unsgdiv:
lea 4(sp),a0
movem.l d2-d3,-(sp)
move.l (a0),d0
move.l d0,d2
move.l 16(sp),d1
move.l d1,d3
cmpi.l #$10000,d1
bge.s adjust
clr.w d0
swap d0
divu d1,d0
move.w d0,d3
move.w d2,d0
divu d1,d0
swap d0
move.w d3,d0
swap d0
bra.s fini
adjust:
lsr.l #1,d0
lsr.l #1,d1
cmpi.l #$10000,d1
bge.s adjust
divu d1,d0
andi.l #$FFFF,d0
move.l d3,d1
swap d1
mulu d0,d1
swap d1
clr.w d1
mulu d0,d3
add.l d3,d1
cmp.l d1,d2
bge.s fini
subq.l #1,d0
fini:
move.l d0,(a0)
movem.l (sp)+,d3-d2
rts